package com.chaoxi.picturebackend.manager.upload;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import com.chaoxi.picturebackend.constant.PictureConstant;
import com.chaoxi.picturebackend.exception.BusinessException;
import com.chaoxi.picturebackend.exception.ErrorCode;
import com.chaoxi.picturebackend.manager.OSSManager;
import com.chaoxi.picturebackend.model.dto.file.UploadPictureResult;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import javax.annotation.Resource;
import java.io.File;
import java.util.Date;

@Slf4j
public abstract class PictureUploadTemplate {

    @Resource
    protected OSSManager ossManager;
    /**
     * 模板方法，定义上传流程  
     */
    public final UploadPictureResult uploadPicture(Object inputSource, String uploadPathPrefix) {
        // 1. 校验图片  
        validPicture(inputSource);

        // 2. 图片上传地址
        String uuid = RandomUtil.randomString(16);
        String originFilename = getOriginFilename(inputSource);
        // 获取图片后缀
        String fileSuffix = FileUtil.getSuffix(originFilename);
        if (fileSuffix == null || fileSuffix.isEmpty()) {
            // 如果没有后缀，默认使用png
            fileSuffix = "png";
        }
        // 根据是否转换为webp格式来决定文件后缀
        // 如果进行了webp转换，则使用webp后缀，否则使用原始后缀
        String compressedFileSuffix = fileSuffix;
        boolean convertToWebp = shouldConvertToWebp(fileSuffix);
        if (convertToWebp) {
            compressedFileSuffix = "webp";
        }
        
        String uploadFilename = String.format("%s_%s.%s", DateUtil.formatDate(new Date()), uuid, compressedFileSuffix);
        // 原图路径
        String originPath = String.format("%s/%s/%s", uploadPathPrefix, "origin", uploadFilename);
        // 压缩图路径
        String compressedPath = String.format("%s/%s/%s", uploadPathPrefix, "compress", uploadFilename);
        // 缩略图路径
        String thumbnailPath = String.format("%s/%s/%s", uploadPathPrefix, "thumbnail" ,uploadFilename);
        log.info("上传图片路径：{}", originPath);
        log.info("上传图片路径：{}", compressedPath);
        log.info("上传图片路径：{}", thumbnailPath);

        File file = null;
        File compressedFile = null;
        File thumbnailFile = null;
        String thumbnailUrl = null;
        try {
            // 3. 创建临时文件，使用简单且安全的名称
            String tempFileName = uuid;
            String suffix = FileUtil.getSuffix(originFilename);
            if (suffix == null || suffix.isEmpty()) {
                suffix = "tmp";
            }
            file = File.createTempFile(tempFileName, "." + suffix);
            // 处理文件来源（本地或 URL）
            processFile(inputSource, file);
            
            // 4. 上传前压缩
            if (convertToWebp) {
                compressedFile = File.createTempFile("compressed", ".webp");
                Thumbnails.of(file)
                        // 缩放为原来的80%
                        .scale(0.8)
                        // 输出质量为80%
                        .outputQuality(0.8)
                        // 输出格式为webp
                        .outputFormat("webp")
                        .toFile(compressedFile);
            } else {
                // 不转换格式，只压缩
                compressedFile = File.createTempFile("compressed", "." + fileSuffix);
                Thumbnails.of(file)
                        // 缩放为原来的80%
                        .scale(0.8)
                        // 输出质量为80%
                        .outputQuality(0.8)
                        // 指定输出格式与文件后缀一致
                        .outputFormat(fileSuffix)
                        .toFile(compressedFile);
            }
            // 缩略图默认为压缩图
            thumbnailFile = compressedFile;
            // 仅对大小>20kb的图片进行缩略图处理
            if (compressedFile.length() > 20 * 1024) {
                // 5. 生成缩略图
                if (convertToWebp) {
                    Thumbnails.of(compressedFile)
                            .size(PictureConstant.THUMBNAIL_WIDTH, PictureConstant.THUMBNAIL_HEIGHT)
                            .outputFormat("webp")
                            .toFile(thumbnailFile);
                } else {
                    Thumbnails.of(compressedFile)
                            .size(PictureConstant.THUMBNAIL_WIDTH, PictureConstant.THUMBNAIL_HEIGHT)
                            // 指定输出格式与原文件一致
                            .outputFormat(fileSuffix)
                            .toFile(thumbnailFile);
                }
                // 压缩了才上传
                thumbnailUrl = ossManager.upload(thumbnailPath, thumbnailFile);
            }

            // 6. 上传原图、压缩图到对象存储
            String originalUrl = ossManager.upload(originPath, file);
            String compressedUrl =  ossManager.upload(compressedPath, compressedFile);

            // 获取上传后的图片元数据信息
            JSONObject originalBasicInfoJsonObject = ossManager.getBasicInfoPictureJson(originPath);
            JSONObject originalColorInfoPictureJson = ossManager.getColorInfoPictureJson(originPath);
            JSONObject compressedBasicInfoPictureJson = ossManager.getBasicInfoPictureJson(compressedPath);
            JSONObject compressedColorInfoPictureJson = ossManager.getColorInfoPictureJson(compressedPath);
            log.info("原图片元数据信息：{}", originalBasicInfoJsonObject);
            log.info("原图片元数据信息：{}", originalColorInfoPictureJson);
            JSONObject compressedJsonObject = ossManager.getBasicInfoPictureJson(compressedPath);
            
            // 只有当缩略图被上传时才获取其元数据
            JSONObject thumbnailBasicInfoPictureJson, thumbnailColorInfoPictureJson = null;
            if (thumbnailUrl != null) {
                thumbnailBasicInfoPictureJson = ossManager.getBasicInfoPictureJson(thumbnailPath);
                thumbnailColorInfoPictureJson = ossManager.getColorInfoPictureJson(thumbnailPath);
            }
            // 7. 封装返回结果,优先压缩图
            return buildResult(originFilename, file , originalUrl, compressedUrl, thumbnailUrl, originalBasicInfoJsonObject,originalColorInfoPictureJson);

        } catch (Exception e) {
            log.error("图片上传到对象存储失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传失败: " + e.getMessage());
        } finally {
            // 8. 清理临时文件  
            deleteTempFile(file);
            deleteTempFile(compressedFile);
        }
    }
    
    /**
     * 判断是否需要转换为WebP格式
     * @param fileSuffix 文件后缀
     * @return 是否需要转换为WebP
     */
    protected boolean shouldConvertToWebp(String fileSuffix) {
        // 如果文件后缀为空，不转换
        if (fileSuffix == null || fileSuffix.isEmpty()) {
            return false;
        }
        // 统一转为小写进行比较
        String suffix = fileSuffix.toLowerCase();
        // 如果已经是webp格式，无需转换
        if ("webp".equals(suffix)) {
            return false;
        }
        // 对于以下格式，建议转换为WebP以减小文件大小
        // JPEG/JPG, PNG, BMP等常见格式
//        return "jpg".equals(suffix) || "jpeg".equals(suffix) || "png".equals(suffix) || "bmp".equals(suffix);
        return false;
    }

    /**
     * 校验输入源（本地文件或 URL）  
     */
    protected abstract void validPicture(Object inputSource);

    /**
     * 获取输入源的原始文件名  
     */
    protected abstract String getOriginFilename(Object inputSource);

    /**
     * 处理输入源并生成本地临时文件  
     */
    protected abstract void processFile(Object inputSource, File file) throws Exception;

    /**
     * 构建上传结果
     */
    private UploadPictureResult buildResult(String originFilename, File file, String originalUrl, String webpUrl, String thumbnailUrl, JSONObject originalBasicInfoJsonObject, JSONObject originalColorInfoPictureJson) {
        UploadPictureResult uploadPictureResult = new UploadPictureResult();
        int imageHeight = Integer.parseInt(originalBasicInfoJsonObject.getJSONObject("ImageHeight").getStr("value"));
        int imageWidth = Integer.parseInt(originalBasicInfoJsonObject.getJSONObject("ImageWidth").getStr("value"));
        String format = originalBasicInfoJsonObject.getJSONObject("Format").getStr("value");
        double picScale = NumberUtil.round(imageWidth * 1.0 / imageHeight, 2).doubleValue();
        // 获取主色调
        String picColor = originalColorInfoPictureJson.getStr("RGB");

        uploadPictureResult.setPicName(FileUtil.mainName(originFilename));
        uploadPictureResult.setPicWidth(imageWidth);
        uploadPictureResult.setPicHeight(imageHeight);
        uploadPictureResult.setPicScale(picScale);
        uploadPictureResult.setPicFormat(format);
        // 原图大小
        uploadPictureResult.setPicSize(FileUtil.size(file));
        uploadPictureResult.setOriginUrl(originalUrl);
        uploadPictureResult.setCompressUrl(webpUrl);
        uploadPictureResult.setThumbnailUrl(thumbnailUrl);
        uploadPictureResult.setPicColor(picColor);
        return uploadPictureResult;
    }

    /**
     * 删除临时文件  
     */
    public void deleteTempFile(File file) {
        if (file == null) {
            return;
        }
        boolean deleteResult = file.delete();
        if (!deleteResult) {
            log.error("file delete error, filepath = {}", file.getAbsolutePath());
        }
    }
}